<template>
    <el-space wrap>
        <el-badge v-if="local.lng" value="纬度" type="success">
            <el-button text bg type="primary">{{ local.lng }}</el-button>
        </el-badge>
        <el-badge v-if="local.lat" value="经度" type="success">
            <el-button text bg type="primary"> {{ local.lat }}</el-button>
        </el-badge>

        <el-button @click="onOpen" type="primary" :icon="Position">
            打开地图
        </el-button>
    </el-space>

    <Dialog v-model="isShow" title="选择经纬度" append-to-body>
        <div class="address">
            <el-alert type="success" :closable="false">
                <template #title>
                    <el-text>当前标记点:&nbsp;&nbsp;</el-text>
                    {{ local.address }}
                </template>
            </el-alert>
        </div>

        <div class="main-wrap">
            <!-- 搜索框 -->
            <div class="search">
                <el-select v-model="keywords" filterable remote reserve-keyword :remote-method="remoteMethod"
                           :loading="loading" clearable @change="currentSelect" style="width: 100%">
                    <el-option v-for="item in options" :key="item.id" :label="item.name" :value="item">
                        <span style="float: left">{{ item.name }}</span>
                        <span style="float: right; color: var(--el-text-color-secondary); font-size: 13px;">
                            {{ item.district }}
                        </span>
                    </el-option>
                </el-select>
            </div>
            <!-- 高德地图 -->
            <div id="container"/>
        </div>

        <template #footer>
            <el-button @click="onSubmit" type="primary">确 定</el-button>
            <el-button @click="isShow = false">取 消</el-button>
        </template>
    </Dialog>
</template>

<script lang="ts" setup>
import {Position} from "@element-plus/icons-vue";
import AMapLoader from '@amap/amap-jsapi-loader';
import {shallowRef} from '@vue/reactivity'

defineOptions({name: 'Map'})

window._AMapSecurityConfig = {
    securityJsCode: "ffe85596ecb104dd0200ec9a3a43c626",
};

const emits = defineEmits(["update:location"]);
const props = defineProps({
    location: {type: Array<number>, required: true},
});

const isShow = ref<boolean>(false);     // 开启弹窗
const keywords = ref<string>("");       // 关键字
const loading = ref<boolean>(false);    // 加载中
const options = ref<Array<any>>([]);    // 搜索结果
const marker = ref<string>();           // 标记点

const map = shallowRef<any>();          // 地图
const geoCoder = ref<any>();            // 逆向解析
const autoComplete = ref<any>();        // 搜索

const local = ref({
    lng: Number(),
    lat: Number(),
    address: ""
})

function initMap() {
    AMapLoader.load({
        key: "79aa331f0a2fb61d1c80d6142f61e9ce",
        version: "2.0",
        plugins: ["AMap.Geocoder", "AMap.AutoComplete"],
    }).then((AMap) => {
        // 加载插件
        map.value = new AMap.Map("container", {
            viewMode: "3D",
            zoom: 10,
        });

        // 逆向解析插件
        geoCoder.value = new AMap.Geocoder({
            city: "010",        //城市设为北京, 默认: "全国"
            radius: 1000,       //范围, 默认: 500
        });

        // 搜索提示插件
        autoComplete.value = new AMap.AutoComplete({city: "全国"});

        // 点击事件
        map.value.on("click", (e: { lnglat: any }) => {
            local.value.lng = e.lnglat.lng;
            local.value.lat = e.lnglat.lat;

            // 清除点
            removeMarker();
            // 标记点
            setMapMarker();
        })
    }).catch(() => {
        console.log("高德地图加载失败");
    }).finally(() => {
        setMapMarker();
    })
}

// 标记
function setMapMarker() {
    if (local.value.lng && local.value.lat) {
        marker.value = new AMap.Marker({
            map: map.value,
            position: [local.value.lng, local.value.lat],
        });

        toGeoCoder();
        map.value.setFitView();
        map.value.add(marker.value);
    }
}

// 清除标记
function removeMarker() {
    if (marker.value) {
        map.value.remove(marker.value);
    }
}

// 远程搜索
function remoteMethod(query: string) {
    if (query == "") return options.value = [];

    loading.value = true;
    setTimeout(() => {
        try {
            autoComplete.value.search(query, (_status, result) => {
                options.value = result.tips;
                loading.value = false;
            })
        } catch (e) {
            options.value = [];
            loading.value = false;
        }
    }, 300);
}

// 清除选中
function currentSelect(val) {
    if (!val) return;

    local.value.lng = val.location.lng;
    local.value.lat = val.location.lat;

    // 清除点
    removeMarker();
    // 标记点
    setMapMarker();
}

function toGeoCoder() {
    geoCoder.value.getAddress([local.value.lng, local.value.lat], (status, result) => {
        if (status === "complete" && result.regeocode) {
            local.value.address = result.regeocode.formattedAddress;
        }
    });
}

function onOpen() {
    isShow.value = true;
    initMap();
    refreshValues();
}

function onSubmit() {
    isShow.value = false;
    emits("update:location", [local.value.lng, local.value.lat]);
}

function refreshValues() {
    if (props.location && props.location.length >= 2) {
        local.value.lng = props.location[0];
        local.value.lat = props.location[1];
    }
}

watch(
    () => props.location,
    () => {
        refreshValues();
    }
)

watch(
    () => isShow.value,
    () => {
        refreshValues();
    }
)
</script>

<style lang="scss" scoped>
.address {
    margin-bottom: 20px;
}

.main-wrap {
    width: 100%;
    height: 500px;
    position: relative;

    .search {
        position: absolute;
        top: 20px;
        left: 20px;
        width: 420px;
        z-index: 1;
    }

    #container {
        margin: 0;
        padding: 0;
        width: 100%;
        height: 100%;
    }
}
</style>
